﻿//  Copyright (c) 2009 Ray Liang (http://www.dotnetage.com)
//  Dual licensed under the MIT and GPL licenses:
//  http://www.opensource.org/licenses/mit-license.php
//  http://www.gnu.org/licenses/gpl.html
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Collections;
using System.IO;
using System.Web.UI;

namespace DNA.Mvc
{
    /// <summary>
    /// Provides helper methods to build the html elments for hierarchical ui
    /// </summary>
    public class HierarchicalNodeUIBuilder : NodeUIBuilder
    {
        /// <summary>
        /// Write the sibling nodes to result.
        /// </summary>
        /// <param name="node">Specified the node object</param>
        /// <returns>The builder object</returns>
        public HierarchicalNodeUIBuilder WriteSiblingNodes(HierarchicalNode node)
        {
            WriteNodes(node.SiblingNodes);
            return this;
        }

        /// <summary>
        /// Write the node instance into html render result.
        /// </summary>
        /// <param name="node">Sepcified the node object</param>
        /// <returns>The builder object</returns>
        public HierarchicalNodeUIBuilder WriteNode(HierarchicalNode node)
        {
            WriteNode(node, null);
            return this;
        }

        /// <summary>
        /// Write the node instance into html render result.
        /// </summary>
        /// <param name="node">Sepcified the node object</param>
        /// <param name="htmlAttributes">Specified the node html attribute object</param>
        /// <remarks>
        /// The result is in this format: <![CDATA[> 
        ///        <li>
        ///              <a href=[node.NavigateUrl] target='[node.Target]'>
        ///                    <input type='hidden' value='[node.Key]'>
        ///                    <img src='[node.ImageUrl]'>
        ///                    <span>[node.Title]</span>
        ///               </a>     
        ///        </li>
        /// ]]>
        /// a,hidden,img element is optional. if the node property is null or empty the elements will not render.
        /// </remarks>
        /// <returns>The builder object</returns>
        public HierarchicalNodeUIBuilder WriteNode(HierarchicalNode node, object htmlAttributes)
        {
            WriteBeginTag("li",htmlAttributes);
            WriteNodeContent(node);
            WriteEndTag("li");
            return this;
        }

        /// <summary>
        /// Write the nodes into html render result.
        /// </summary>
        /// <remarks>
        /// The result is in this format: <![CDATA[> 
        ///     <ul>
        ///        <li>
        ///              <a href=[node.NavigateUrl] target='[node.Target]'>
        ///                    <input type='hidden' value='[node.Key]'>
        ///                    <img src='[node.ImageUrl]'>
        ///                    <span>[node.Title]</span>
        ///               </a>     
        ///        </li>
        ///        .
        ///        .
        ///        .
        ///      </ul> 
        /// ]]>
        /// a,hidden,img element is optional. if the node property is null or empty the elements will not render.
        /// </remarks>
        /// <param name="nodes">Specified the node collection to write.</param>
        /// <returns>The builder object</returns>
        public HierarchicalNodeUIBuilder WriteNodes(IEnumerable<HierarchicalNode> nodes)
        {
            if (nodes != null)
            {
                WriteFullBeginTag("ul");
                foreach (HierarchicalNode node in nodes)
                    WriteNode(node);
                WriteEndTag("ul");
            }
            return this;
        }

        /// <summary>
        /// Write the nodes into html render result.This method will write the node.Attributes property as 
        /// li element's html attributes
        /// </summary>
        /// <param name="nodes">Specified the node collection to write.</param>
        /// <remarks>
        /// The result is in this format: <![CDATA[> 
        ///     <ul>
        ///        <li node.Attributes.Key=node.Attributes[key] ..... >
        ///              <a href=[node.NavigateUrl] target='[node.Target]'>
        ///                    <input type='hidden' value='[node.Key]'>
        ///                    <img src='[node.ImageUrl]'>
        ///                    <span>[node.Title]</span>
        ///               </a>     
        ///        </li>
        ///        .
        ///        .
        ///        .
        ///      </ul> 
        /// ]]>
        /// a,hidden,img element is optional. if the node property is null or empty the elements will not render.
        /// </remarks>
        /// <returns>The builder object</returns>       
        public HierarchicalNodeUIBuilder WriteNodesWithAllAttributes(IEnumerable<HierarchicalNode> nodes)
        {
            if (nodes != null)
            {
                WriteFullBeginTag("ul");
                foreach (HierarchicalNode node in nodes)
                    WriteNode(node, node.Attributes);
                 WriteEndTag("ul");
            }
            return this;
        }

        public HierarchicalNodeUIBuilder WriteNodesRecursiveWithAllAttributes(IEnumerable<HierarchicalNode> nodes)
        {
            if (nodes != null)
            {
                WriteFullBeginTag("ul");
                foreach (HierarchicalNode node in nodes)
                    WriteNodeRecursiveWithAllAttributes(node);
                WriteEndTag("ul");
            }
            return this;
        }

        public HierarchicalNodeUIBuilder WriteNodeRecursiveWithAllAttributes(HierarchicalNode node)
        {
            WriteBeginTag("li", node.Attributes);
            WriteNodeContent(node);
            if (node.HasChildNodes)
                WriteNodesRecursiveWithAllAttributes(node.ChildNodes);
            WriteEndTag("li");
            return this;
        }

        /// <summary>
        /// Write the li html element to the HtmlTextWriter.
        /// </summary>
        /// <param name="node">The HtmlTextWriter</param>
        /// <param name="htmlAttributes">The html attributes of the li element</param>
        /// <param name="containerAttributes">The html attributes of the ul element</param>
        /// <returns>The builder object</returns>    
        public HierarchicalNodeUIBuilder WriteNodeRecursive(HierarchicalNode node, object htmlAttributes, object containerAttributes)
        {
            WriteBeginTag("li", htmlAttributes);
            WriteNodeContent(node);
            if (node.HasChildNodes)
                WriteNodesRecursive(node.ChildNodes, containerAttributes, htmlAttributes);
            WriteEndTag("li");
            return this;
        }

        /// <summary>
        /// Write the node and it's descendant nodes
        /// </summary>
        /// <param name="node">Specified the node to write</param>
        /// <returns>The builder object</returns>
        public HierarchicalNodeUIBuilder WriteNodeRecursive(HierarchicalNode node)
        {
            WriteNodeRecursive(node, null, null);
            return this;
        }

        /// <summary>
        /// Write the nodes and it's descendant nodes
        /// </summary>
        /// <param name="nodes">Specified the node collection to write to result.</param>
        /// <returns>The builder object</returns>
        public HierarchicalNodeUIBuilder WriteNodesRecursive(IEnumerable<HierarchicalNode> nodes)
        {
            WriteNodesRecursive(nodes, null, null);
            return this;
        }

        /// <summary>
        /// Write the node collection to result recursive.
        /// </summary>
        /// <param name="nodes">Specified node collection to write to result.</param>
        /// <param name="htmlAttributes">Specified  the html attributes of the ul element</param>
        /// <param name="nodeAttributes">Specified  the html attributes of the li element</param>
        /// <returns>The builder object</returns>
        public HierarchicalNodeUIBuilder WriteNodesRecursive(IEnumerable<HierarchicalNode> nodes, object htmlAttributes, object nodeAttributes)
        {
            if (nodes != null)
            {
                WriteBeginTag("ul",htmlAttributes);
                foreach (HierarchicalNode node in nodes)
                    WriteNodeRecursive(node, htmlAttributes, nodeAttributes);
                WriteEndTag("ul");
            }
            return this;
        }

        /// <summary>
        /// Write the html in li element
        /// </summary>
        /// <param name="node">Specified the node object</param>
        /// <remarks>
        /// The result is in this format: 
        /// <![CDATA[> 
        ///              <a href=[node.NavigateUrl] target='[node.Target]'>
        ///                    <input type='hidden' value='[node.Key]'>
        ///                    <img src='[node.ImageUrl]'>
        ///                    <span>[node.Title]</span>
        ///               </a>     
        /// ]]>
        /// a,hidden,img element is optional. if the node property is null or empty the elements will not render.
        /// </remarks>
        /// <returns>The builder object</returns>
        public override NodeUIBuilder WriteNodeContent(INavigable node)
        {
            if (OnContentRender(node))
            {
                if (!string.IsNullOrEmpty(node.NavigateUrl))
                    WriteBeginLink(node);

                if (node.Value != null)
                    WriteHidden(node.Value.ToString());

                if (!string.IsNullOrEmpty(node.ImageUrl))
                    WriteImage(node, new { style = "float:left;" });

                if (string.IsNullOrEmpty(node.NavigateUrl))
                    WriteTitle(node, new { style = "padding:2px;cursor:default;display:inline-block;" });
                else
                    WriteTitle(node, new { style = "padding:2px;cursor:default;display:inline-block;" });

                if (!string.IsNullOrEmpty(node.NavigateUrl))
                    WriteEndTag("a");
            }
            return this;
        }
    }
}
